import React, { useCallback, useMemo } from 'react';
import { StyleSheet, View } from 'react-native';
import { ButtonPressAnimation } from '../animations';
import FastTransactionStatusBadge from './FastTransactionStatusBadge';
import { Bleed, Box, Inline, Text, globalColors, useForegroundColor } from '@/design-system';
import { NativeCurrencyKey, RainbowTransaction, TransactionStatus, TransactionType } from '@/entities';
import { ThemeContextProps } from '@/theme';
import { useNavigation } from '@/navigation';
import Routes from '@rainbow-me/routes';
import { ImgixImage } from '../images';
import { CardSize } from '../unique-token/CardSize';
import { ChainId } from '@/state/backendNetworks/types';
import { address } from '@/utils/abbreviations';
import { TwoCoinsIcon } from '../coin-icon/TwoCoinsIcon';
import Spinner from '../Spinner';

import RainbowCoinIcon from '@/components/coin-icon/RainbowCoinIcon';
import { ChainImage } from '../coin-icon/ChainImage';
import { useSuperTokenStore } from '@/screens/token-launcher/state/rainbowSuperTokenStore';
import { activityValues, useTransactionLaunchToken } from '@/helpers/transactions';

const getIconTopMargin = (type: TransactionType) => {
  switch (type) {
    case 'swap':
      return 1;
    case 'mint':
      return -1;

    default:
      return 0;
  }
};
const activityTypeIcon: Record<TransactionType, string> = {
  airdrop: '􀐚',
  approve: '􀁢',
  contract_interaction: '􀉆',
  receive: '􀄩',
  send: '􀈟',
  swap: '􀖅',
  bid: '􀑍',
  burn: '􀙬',
  mint: '􀫸',
  purchase: '􀍣',
  sale: '􀋡',
  wrap: '􀑉',
  unwrap: '􀑉',
  cancel: '􀁠',
  repay: '􀄹',
  bridge: '􀄹',
  stake: '􀄷',
  unstake: '􀄲',
  withdraw: '􀄲',
  deposit: '􀄷',
  revoke: '􀁎',
  speed_up: '􀓎',
  claim: '􀄩',
  borrow: '􀄩',
  deployment: '􀄩',
  launch: '􀓎',
};

export const ActivityTypeIcon = ({
  transaction: { status, type },
  color,
}: {
  transaction: Pick<RainbowTransaction, 'status' | 'type'>;
  color: string;
}) => {
  if (status === TransactionStatus.pending) {
    return <Spinner color={color} size={11} style={{ marginTop: -1, paddingRight: 2 }} />;
  }

  if (status === 'failed')
    return (
      <Text color={{ custom: color }} weight="semibold" size="12pt" align="center">
        {'􀀲'}
      </Text>
    );

  const symbol = activityTypeIcon[type];
  if (!symbol) return null;
  return (
    <View style={{ marginTop: getIconTopMargin(type) }}>
      <Text color={{ custom: color }} weight="semibold" size="12pt">
        {symbol}
      </Text>
    </View>
  );
};

const BottomRow = React.memo(function BottomRow({
  transaction,
  nativeCurrency,
  theme,
}: {
  transaction: RainbowTransaction;
  nativeCurrency: NativeCurrencyKey;
  theme: ThemeContextProps;
}) {
  const launchToken = useTransactionLaunchToken(transaction);

  const { type, to, asset } = transaction;
  const separatorSecondary = useForegroundColor('separatorSecondary');

  let description = transaction.description;
  let tag: string | undefined;
  if (type === 'contract_interaction' && to) {
    description = transaction.contract?.name || address(to, 6, 4);
    tag = transaction.description;
  }

  if (type === 'launch' && launchToken) {
    description = launchToken?.name;
  }

  if (transaction?.type === 'mint') {
    const inAsset = transaction?.changes?.find(a => a?.direction === 'in')?.asset;
    description = inAsset?.name || '';
  }

  if (['wrap', 'unwrap', 'swap'].includes(transaction?.type)) {
    const inAsset = transaction?.changes?.find(a => a?.direction === 'in')?.asset;
    const outAsset = transaction?.changes?.find(a => a?.direction === 'out')?.asset;

    if (!!inAsset && !!outAsset) description = `${outAsset?.symbol} 􀄫 ${inAsset?.symbol}`;
  }

  const nftChangesAmount = transaction.changes
    ?.filter(c => asset?.address === c?.asset.address && c?.asset.type === 'nft')
    .filter(Boolean).length;
  if (nftChangesAmount) tag = nftChangesAmount.toString();

  const [, bottomValue] = activityValues(transaction, nativeCurrency) ?? [];

  return (
    <View style={sx.bottomRow}>
      <View style={sx.description}>
        <Inline wrap={false} horizontalSpace={'6px'}>
          <Text color={'label'} numberOfLines={1} size="16px / 22px (Deprecated)" weight="regular">
            {description}
          </Text>
          {tag && (
            <Bleed vertical={{ custom: 5 }}>
              <Box
                style={{
                  borderWidth: 1.5,
                  borderColor: theme.colors.alpha(separatorSecondary, 0.2),
                  borderRadius: 8,
                }}
                justifyContent="center"
                alignItems="center"
                padding={{ custom: 5 }}
              >
                <Text align="center" color="labelTertiary" size="13pt" weight="regular">
                  {tag}
                </Text>
              </Box>
            </Bleed>
          )}
        </Inline>
      </View>
      <View style={sx.nativeBalance}>
        <Text
          align="right"
          color={bottomValue?.includes('+') ? 'green' : 'labelSecondary'}
          size="16px / 22px (Deprecated)"
          weight={'regular'}
          numberOfLines={1}
        >
          {bottomValue}
        </Text>
      </View>
    </View>
  );
});

export const ActivityIcon = ({
  transaction,
  size = 40,
  badge = true,
  theme,
}: {
  transaction: RainbowTransaction;
  badge?: boolean;
  size?: 40 | 20 | 14 | 16;
  theme: ThemeContextProps;
}) => {
  const rainbowSuperToken = useMemo(() => {
    if (transaction?.type === 'launch') {
      return useSuperTokenStore.getState().getSuperTokenByTransactionHash(transaction.hash);
    }
    return undefined;
  }, [transaction.hash, transaction.type]);

  if (['wrap', 'unwrap', 'swap'].includes(transaction?.type)) {
    const inAsset = transaction?.changes?.find(a => a?.direction === 'in')?.asset;
    const outAsset = transaction?.changes?.find(a => a?.direction === 'out')?.asset;

    if (!!inAsset?.icon_url && !!outAsset?.icon_url)
      return <TwoCoinsIcon over={inAsset} under={outAsset} badge={badge && transaction.chainId !== ChainId.mainnet} />;
  }

  let contractIconUrl = transaction?.contract?.iconUrl;
  let coinIconUrl = transaction?.asset?.icon_url;
  if (transaction?.type === 'launch') {
    if (rainbowSuperToken) {
      if (transaction.asset?.colors && rainbowSuperToken?.color) {
        transaction.asset.colors.primary = rainbowSuperToken?.color;
      }
      coinIconUrl = rainbowSuperToken?.imageUrl;
    }
    contractIconUrl = undefined;
  }

  if (contractIconUrl) {
    return (
      <View style={sx.iconContainer}>
        <RainbowCoinIcon
          icon={contractIconUrl}
          chainId={transaction?.asset?.chainId || ChainId.mainnet}
          symbol={transaction?.asset?.symbol || ''}
          color={transaction?.asset?.colors?.primary || transaction?.asset?.colors?.fallback || undefined}
        />
      </View>
    );
  }

  // fallback for contracts that we dont have data for
  if (transaction?.type === 'contract_interaction') {
    return (
      <Box
        alignItems="center"
        background="fillSecondary"
        borderRadius={10}
        height={{ custom: size }}
        justifyContent="center"
        style={{ opacity: theme.isDarkMode ? 0.5 : 0.75 }}
        width={{ custom: size }}
      >
        <Text align="center" color="labelQuaternary" size="icon 16px" weight="bold">
          􀎭
        </Text>
      </Box>
    );
  }

  if (transaction?.asset?.type === 'nft') {
    return (
      <View
        style={{
          shadowColor: globalColors.grey100,
          shadowOffset: { width: 0, height: 2 },
          shadowOpacity: 0.02,
          shadowRadius: 3,
          overflow: 'visible',
        }}
      >
        <View
          style={{
            shadowColor: !transaction?.asset?.color ? globalColors.grey100 : transaction.asset.color,
            shadowOffset: { width: 0, height: 6 },
            shadowOpacity: 0.24,
            shadowRadius: 9,
          }}
        >
          {/* @ts-expect-error local nft assets have diff types */}
          {transaction.asset.icon_url || transaction.asset.image_url ? (
            <ImgixImage
              size={CardSize}
              style={{
                width: size,
                height: size,
                borderRadius: 10,
              }}
              source={{
                // @ts-expect-error local nft assets have diff types
                uri: transaction.asset.icon_url || transaction.asset.image_url,
              }}
            />
          ) : (
            <Box
              alignItems="center"
              background="fillSecondary"
              borderRadius={10}
              height={{ custom: size }}
              justifyContent="center"
              style={{ opacity: theme.isDarkMode ? 0.5 : 0.75 }}
              width={{ custom: size }}
            >
              <Text align="center" color="labelQuaternary" size="icon 16px" weight="bold">
                􀏆
              </Text>
            </Box>
          )}
        </View>
        <ChainImage badgeXPosition={-10} chainId={transaction.chainId} showBadge={badge && transaction.chainId !== ChainId.mainnet} />
      </View>
    );
  }

  return (
    <View style={sx.iconContainer}>
      <RainbowCoinIcon
        icon={coinIconUrl}
        chainId={transaction?.asset?.chainId || ChainId.mainnet}
        symbol={transaction?.asset?.symbol || ''}
        color={transaction?.asset?.colors?.primary || transaction?.asset?.colors?.fallback || undefined}
      />
    </View>
  );
};

export default React.memo(function TransactionCoinRow({
  item,
  nativeCurrency,
  theme,
}: {
  item: RainbowTransaction;
  nativeCurrency: NativeCurrencyKey;
  theme: ThemeContextProps;
}) {
  const { colors } = theme;
  const { navigate } = useNavigation();

  const onPress = useCallback(() => {
    navigate(Routes.TRANSACTION_DETAILS, {
      transaction: item,
    });
  }, [item, navigate]);

  const [topValue] = activityValues(item, nativeCurrency) ?? [];

  return (
    <ButtonPressAnimation onPress={onPress} scaleTo={0.96} uniqueId={`${item.hash}-${item.chainId}`}>
      <View style={sx.wholeRow} testID={`${item.title}-${item.description}-${item.balance?.display}`}>
        <View style={sx.icon}>
          <ActivityIcon transaction={item} theme={theme} />
        </View>

        <View style={sx.column}>
          <View style={sx.topRow}>
            <FastTransactionStatusBadge colors={colors} transaction={item} />
            <View style={sx.balance}>
              <Text color={'labelTertiary'} numberOfLines={1} size="14px / 19px (Deprecated)">
                {topValue}
              </Text>
            </View>
          </View>
          <BottomRow transaction={item} theme={theme} nativeCurrency={nativeCurrency} />
        </View>
      </View>
    </ButtonPressAnimation>
  );
});

const sx = StyleSheet.create({
  balance: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    paddingLeft: 8,
  },
  iconContainer: {
    elevation: 6,
    height: 59,
    overflow: 'visible',
    paddingTop: 9,
  },
  bottomRow: {
    alignItems: 'flex-end',
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginTop: 10,
  },
  column: {
    flex: 1,
    justifyContent: 'center',
    marginLeft: 10,
  },
  description: {
    flex: 1,
    maxWidth: '50%',
  },
  icon: {
    justifyContent: 'center',
  },
  nativeBalance: {
    marginLeft: 16,
  },
  topRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  wholeRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingHorizontal: 19,
    overflow: 'visible',
    height: 59,
  },
});
